; this is the seed critter.

(def *mutation-rate* 0.10) ; the probability of each form mutating

(declare mutate)

(defmacro equal-chance
  "Picks a random expr with equal probability and evaluates it."
  [& exprs]
  `((rand-nth [~@(map (fn [expr] `(fn [] ~expr)) exprs)])))

(defn deletion-mutation
  "Deletes the first form, mutates the rest, and returns it."
  [code]
  ;(println "deletion-mutation") ;debug
  (mutate (rest code)))

(defn duplication-mutation
  "Copies the first form, mutates the rest, and returns them."
  [code]
  ;(println "duplication-mutation") ;debug
  (cons (first code) (mutate code)))

(defn mutate
  "Goes through each form in code and mutates it with probability
  *mutation-rate*. Returns the result. Note that *mutation-rate* is the
  probability that each form in the code will be mutated."
  [code]
  (if (and (coll? (first code))
           (not (empty? code)))
    ; code is a list of exprs
    (if (< (rand) *mutation-rate*)
      ; mutation triggered
      (do
        ;(println "mutation triggered") ;debug
	      (equal-chance ; do one of these, with equal chance
	        (deletion-mutation code)
	        (duplication-mutation code)
	        ; (add more types of mutation here)
	        ))
      ; no mutation yet, continue
      (cons (mutate (first code)) (mutate (rest code))))
    ; code is an expr or an empty list
    (do
      ;(println "reached expr or empty list") ;debug
      code)))

;testing stuff
(println "Original:")
(println (str self-code))
(println)
(println "Mutations:")
(dotimes [i 10] ; does 10 mutations and prints the results
  (println (str (mutate self-code))))